package com.yin.waimai.config;

import com.yin.waimai.service.AppUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import jakarta.servlet.http.HttpServletResponse;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig {

    @Autowired
    private AppUserDetailsService appUserDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder =
                http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.userDetailsService(appUserDetailsService)
                .passwordEncoder(passwordEncoder());
        return authenticationManagerBuilder.build();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(authorizeRequests ->
                        authorizeRequests
                                // 允许静态资源和前端页面匿名访问
                                .requestMatchers("/", "/index.html", "/profile.html", "/api_tester.html", "/login.html", "/register.html", "/admin-login.html", "/css/**", "/js/**", "/images/**").permitAll()

                                // 允许注册API匿名访问
                                .requestMatchers(HttpMethod.POST, "/api/v1/auth/register").permitAll()

                                // 允许订单查询和路径查询API匿名访问
                                .requestMatchers(HttpMethod.GET, "/api/v1/orders/{orderNumber}").permitAll()
                                .requestMatchers(HttpMethod.GET, "/api/v1/orders/{orderNumber}/traces").permitAll()
                                .requestMatchers(HttpMethod.GET, "/api/v1/orders/{orderNumber}/path").permitAll()
                                
                                // 配送员专用API
                                .requestMatchers("/api/v1/delivery/**").hasRole("DELIVERY_PERSON")
                                
                                // 管理员专用API和页面 - 临时允许匿名访问
                                .requestMatchers("/api/v1/admin/**").permitAll() // 临时允许匿名访问
                                .requestMatchers("/admin/**").permitAll() // 临时允许匿名访问
                                
                                // 恢复正常权限控制时改回：
                                // .requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
                                // .requestMatchers("/admin/**").hasRole("ADMIN")

                                // 其他所有请求都需要认证
                                .anyRequest().authenticated()
                )
                .formLogin(formLogin ->
                        formLogin
                                .loginPage("/login.html") // 普通用户登录页面
                                .loginProcessingUrl("/perform_login") // Spring Security 处理登录的URL
                                .defaultSuccessUrl("/index.html") // 普通用户登录成功后跳转的页面
                                .successHandler((request, response, authentication) -> {
                                    // 检查是否有ADMIN角色
                                    boolean isAdmin = authentication.getAuthorities().stream()
                                            .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"));
                                    
                                    if (isAdmin) {
                                        // 管理员跳转到仪表盘
                                        response.sendRedirect("/admin/dashboard.html#");
                                    } else {
                                        // 普通用户跳转到首页
                                        response.sendRedirect("/index.html");
                                    }
                                })
                                .failureUrl("/login.html?error=true") // 登录失败后跳转的页面
                                .permitAll()
                )
                // 添加这个新的配置，为管理员页面设置专门的访问拒绝处理
                .exceptionHandling(exceptionHandling ->
                        exceptionHandling
                                .accessDeniedHandler((request, response, accessDeniedException) -> {
                                    // 记录访问被拒绝的信息
                                    System.out.println("访问被拒绝: " + request.getRequestURI());
                                    // 如果是尝试访问管理员页面被拒绝，重定向到管理员登录页面
                                    String requestURI = request.getRequestURI();
                                    if (requestURI.startsWith("/admin/") || requestURI.startsWith("/api/v1/admin/")) {
                                        // 检查用户是否已经登录
                                        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
                                        if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken)) {
                                            // 用户已登录但权限不足，显示错误页面或返回403
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足");
                                        } else {
                                            // 用户未登录，重定向到管理员登录页面
                                            response.sendRedirect("/admin-login.html");
                                        }
                                    } else {
                                        // 其他访问拒绝情况，重定向到普通登录页面
                                        response.sendRedirect("/login.html?access_denied=true");
                                    }
                                })
                                // 为未认证的用户设置自定义处理
                                .authenticationEntryPoint((request, response, authException) -> {
                                    // 记录未认证的请求
                                    System.out.println("未认证的请求: " + request.getRequestURI());
                                    // 如果是尝试访问管理员页面，重定向到管理员登录页面
                                    String requestURI = request.getRequestURI();
                                    if (requestURI.startsWith("/admin/") || requestURI.startsWith("/api/v1/admin/")) {
                                        response.sendRedirect("/admin-login.html");
                                    } else {
                                        // 其他未认证情况，重定向到普通登录页面
                                        response.sendRedirect("/login.html");
                                    }
                                })
                )
                .logout(logout ->
                        logout
                                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                                .logoutSuccessUrl("/login.html?logout=true") // 登出成功后跳转
                                .invalidateHttpSession(true) // 使session失效
                                .deleteCookies("JSESSIONID") // 删除cookie
                                .permitAll()
                );

        return http.build();
    }
}